from django.shortcuts import render, HttpResponse
from django import forms
from django.forms import formset_factory  # 批量form生成

from app01 import models


class MultiPermissionForm(forms.Form):
    """定义的Form新增"""
    title = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control'})
    )
    url = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control'})
    )
    name = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control'})
    )
    # 关联id
    menu_id = forms.ChoiceField(
        choices=[(None, '-----')],  # 默认选项空
        widget=forms.Select(attrs={'class': 'form-control'}),
        required=False,
    )
    # 关联id
    pid_id = forms.ChoiceField(
        choices=[(None, '-----')],  # 默认选项空
        widget=forms.Select(attrs={'class': 'form-control'}),
        required=False,
    )

    def __init__(self, *args, **kwargs):  # 自写重写构造方法，把下拉框功能写进去
        super().__init__(*args, **kwargs)
        self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title')  # 取列表用values_list
        self.fields['pid_id'].choices += models.Permission.objects.filter(pid__isnull=True).exclude(
            menu__isnull=True).values_list('id', 'title')  # 可以做菜单的权限添加


def multi_add(request):
    """批量添加"""
    formset_class = formset_factory(MultiPermissionForm, extra=2)  # 利用formset_factory 将 Form实例化【2个对象】（列表）
    if request.method == 'GET':
        formset = formset_class()  # 然后将这个类实例化即可
        return render(request, 'multi_add.html', {'formset': formset})

    # POST 提交
    formset = formset_class(data=request.POST)
    if formset.is_valid():  # 校验 【注意，字段内有唯一字段必须做联合唯一try捕获】
        flag = True
        '''因为有联合唯一，额外的错误提示，所以用 for range下标循环来做，某一项错误单独给xxx[i].errors来添加错误信息'''
        post_row_list = formset.cleaned_data  # 如果没有错误信息，吧用户提交的数据获取【注意】因为cleaned_data 与 errors 互斥，所以要单独存放
        for i in range(0, formset.total_form_count()):
            row = post_row_list[i]  # 取出
            if not row:
                continue  # 如果空，就不提交
            try:
                obj = models.Permission(**row)
                obj.validate_unique()  # 检查是否有 联合唯一的字段异常（如果错误就会抛出异常）
                obj.save()
            except Exception as e:
                formset.errors[i].update(e)  # update 加入错误信息提示
                flag = False
        if flag:
            return HttpResponse('添加成功')

    return render(request, 'multi_add.html', {'formset': formset})



class MultiUpdatePermissionForm(forms.Form):
    """定义的Form修改"""
    id = forms.IntegerField(
        widget=forms.HiddenInput()  # Hidden 隐藏的表格
    )
    title = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control'})
    )
    url = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control'})
    )
    name = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control'})
    )
    # 关联id
    menu_id = forms.ChoiceField(
        choices=[(None, '-----')],  # 默认选项空
        widget=forms.Select(attrs={'class': 'form-control'}),
        required=False,
    )
    # 关联id
    pid_id = forms.ChoiceField(
        choices=[(None, '-----')],  # 默认选项空
        widget=forms.Select(attrs={'class': 'form-control'}),
        required=False,
    )

    def __init__(self, *args, **kwargs):  # 自写重写构造方法，把下拉框功能写进去
        super().__init__(*args, **kwargs)
        self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title')  # 取列表用values_list
        self.fields['pid_id'].choices += models.Permission.objects.filter(pid__isnull=True).exclude(
            menu__isnull=True).values_list('id', 'title')  # 可以做菜单的权限添加


def multi_edit(request):
    """批量修改"""
    formset_class = formset_factory(MultiUpdatePermissionForm, extra=0)  # extra=0 不额外增加

    if request.method == 'GET':
        formset = formset_class(
            initial=models.Permission.objects.all().values('id', 'title', 'name', 'url', 'menu_id', 'pid_id')
        )  # 将原有值填入，等待修改
        return render(request, 'multi_edit.html', {'formset': formset})

    # POST 提交
    formset = formset_class(data=request.POST)
    if formset.is_valid():  # 校验 【注意，字段内有唯一字段必须做联合唯一try捕获】
        post_row_list = formset.cleaned_data  # 如果没有错误信息，吧用户提交的数据获取【注意】因为cleaned_data 与 errors 互斥，所以要单独存放
        flag = True
        for i in range(0, formset.total_form_count()):
            row = post_row_list[i]  # 取出
            if not row:
                continue  # 如果空，就不提交
            permission_id = row.pop('id')
            # 有可能出现，联合唯一字段重复，要进行判断
            try:
                permission_obj = models.Permission.objects.filter(id=permission_id).first()
                # permission_obj.title = row['title']
                # permission_obj.url = row['url']
                # permission_obj.name = row['name']
                # permission_obj.menu_id = row['menu_id']
                # permission_obj.pid_id = row['pid_id']

                '''利用反射简化上面注释的部分(效果一样)'''
                for key, value in row.items():
                    setattr(permission_obj, key, value)
                permission_obj.validate_unique()
                permission_obj.save()
            except Exception as e:
                formset.errors[i].update(e)
                flag = False
        if flag:
            return HttpResponse('更新成功')

    return render(request, 'multi_edit.html', {'formset': formset})